//file: libc/include/signal.c
//autor:jiangxinpeng
//time:2021.8.23
//copyright:(C) 2020-2050 by jiangxinpeng,All right are reserved.

#ifndef __LIBC_SIGNAL_H
#define __LIBC_SIGNAL_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "ctype.h"
#include <sys/exception.h>

//signal define
#define SIGINT EXC_CODE_INT
#define SIGILL EXC_CODE_ILL
#define SIGTRAP EXC_CODE_TRAP
#define SIGABRT EXC_CODE_ABORT
#define SIGBUS EXC_CODE_BUS
#define SIGFPE EXC_CODE_FPE
#define SIGKILL EXC_CODE_FINALHIT
#define SIGUSER1 EXC_CODE_USER
#define SIGSEGV EXC_CODE_SEGV
#define SIGPIPE EXC_CODE_PIPE
#define SIGALRM EXC_CODE_ALRM
#define SIGTERM EXC_CODE_TERM
#define SIGSTKFLT EXC_CODE_STKFLT
#define SIGCHLD EXC_CODE_CHLD
#define SIGCONT EXC_CODE_CONT
#define SIGSTOP EXC_CODE_STOP
#define SIGTSTP SIGSTOP
#define SIGTTIN EXC_CODE_TTIN
#define SIGTTOU EXC_CODE_TTOU
#define SIGSYS EXC_CODE_SYS
#define SIGIO EXC_CODE_DEVICE
#define SIG_UNUSE EXC_CODE_MAX
#define SIGHUP (SIG_UNUSE + 0)
#define SIGWINCH (SIG_UNUSE + 1)
#define SIGVTALRM (SIG_UNUSE + 2)
#define SIGPROF (SIG_UNUSE + 3)
#define SIGQUIT (SIG_UNUSE + 4)

#define NSIG SIGQUIT + 1

    typedef void (*sign_handler_t)();

    typedef uint64_t signset_t;

#ifndef _SIG_ATOMIC_T_DEFINED
#define _SIG_ATOMIC_T_DEFINED
    typedef int sign_atomic_t;
#endif

//bad signal macro
#define IS_BAD_SIGNAL(signo) \
    (signo < 1 || signo >= NSIG)

    typedef struct signaction
    {
        sign_handler_t action_func; //default handler
        int action_flags;           //action flags
        signset_t action_mask;      //action mask set
    } signaction_t;

#define SIG_DFL ((sign_handler_t)0)       //defalut action
#define SIG_IGN ((sign_handler_t)1)       //ignore signal
#define SIG_BLOCKED ((sign_handler_t)2)   //block signal
#define SIG_UNBLOCKED ((sign_handler_t)3) //unblock signal

#define SIG_BLOCK 1   //add targe set in block signal set
#define SIG_UNBLOCK 2 //del targe set in block signal set
#define SIG_SETMASK 3 //set block signal set

    int signal(int signo, sign_handler_t handler);
    int signprocmask(int how, const signset_t *set, signset_t *oldset);

    static inline int kill(pid_t pid, int signo)
    {
        return excsend(pid, signo);
    }

    static inline int raise(int signo)
    {
        return excraise(signo);
    }

    static inline int signaction(int signo, const signaction_t *new_act, signaction_t *old_act)
    {
        if (IS_BAD_SIGNAL(signo))
            return -1;
        if (old_act)
        {
            old_act->action_func = (sign_handler_t)exchandler(signo);
            old_act->action_flags = 0;
            old_act->action_mask = 0;
        }
        //set new action
        return signal(signo, new_act->action_func);
    }

    static inline int signaddset(signset_t *mask, int signo)
    {
        if (IS_BAD_SIGNAL(signo))
            return -1;
        *mask |= (1 << signo);
        return 0;
    }

    static inline int signdelset(signset_t *mask, int signo)
    {
        if (IS_BAD_SIGNAL(signo))
            return -1;
        *mask &= ~(1 << signo);
        return 0;
    }

    static inline int signemptyset(signset_t *mask)
    {
        *mask = 1;
        return 0;
    }

    static inline int signfillset(signset_t *mask)
    {
        *mask = 0xffffffff;
        return 0;
    }

    static inline int signismember(signset_t *mask, int signo)
    {
        if (IS_BAD_SIGNAL(signo))
            return 0;
        return (*mask & (1 << signo));
    }

    static inline int signisempty(signset_t *mask)
    {
        return !(*mask > 1);
    }

    static inline int signisfull(signset_t *mask)
    {
        return (*mask == 0xFFFFFFFF);
    }

#ifdef __cplusplus
}
#endif
#endif